package com.linkgie.galaxyframework.crypto;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 加密操作；
 * 
 * @author liso
 *
 * @param <EK> 加密密钥；
 * @param <DK> 解密密钥；
 */
public interface StreamingCipherFunc<EK extends Cryptogram, DK extends Cryptogram> extends CipherFunc<EK, DK> {

	/**
	 * 加密数据；
	 * 
	 * @param pubKey     公钥；
	 * @param plainBytes 明文数据；
	 * @return 密文数据；
	 */
	@Override
	default byte[] encrypt(EK key, byte[] plainBytes) {
		ByteArrayInputStream in = new ByteArrayInputStream(plainBytes);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		encrypt(key, in, out);
		return out.toByteArray();
	}

	/**
	 * 加密数据；
	 * 
	 * @param pubKey     公钥；
	 * @param plainBytes 明文数据；；
	 * @param offset     明文输入偏移；
	 * @param length     明文输入长度；
	 * @return 密文数据；
	 */
	@Override
	default byte[] encrypt(EK key, byte[] plainBytes, int offset, int length) {
		ByteArrayInputStream in = new ByteArrayInputStream(plainBytes, offset, length);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		encrypt(key, in, out);
		return out.toByteArray();
	}

	/**
	 * 加密数据；
	 * 
	 * @param pubKey     公钥；
	 * @param plainBytes 明文数据；；
	 * @param offset     明文输入偏移；
	 * @param length     明文输入长度；
	 * @param out        密文输出；
	 * @return 密文输出长度；
	 */
	@Override
	default int encrypt(EK key, byte[] plainBytes, int offset, int length, OutputStream out) {
		ByteArrayInputStream in = new ByteArrayInputStream(plainBytes, offset, length);
		return encrypt(key, in, out);
	}

	/**
	 * 加密数据；
	 * 
	 * @param kKey       加密密钥；
	 * @param plainBytes 明文数据；；
	 * @param offset     明文输入偏移；
	 * @param length     明文输入长度；
	 * @param out        密文输出；
	 * @return 密文输出长度；
	 */
	int encrypt(EK key, InputStream in, OutputStream out);

	/**
	 * 加密数据；
	 * 
	 * @param rawKey     未编码的原加密密钥；
	 * @param plainBytes 明文数据；
	 * @return 密文数据；
	 */
	@Override
	default byte[] encrypt(byte[] rawKey, byte[] plainBytes) {
		ByteArrayInputStream in = new ByteArrayInputStream(plainBytes);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		encrypt(rawKey, in, out);
		return out.toByteArray();
	}

	/**
	 * 加密数据；
	 * 
	 * @param rawKey     未编码的原加密密钥；
	 * @param plainBytes 明文数据；；
	 * @param offset     明文输入偏移；
	 * @param length     明文输入长度；
	 * @return 密文数据；
	 */
	@Override
	default byte[] encrypt(byte[] rawKey, byte[] plainBytes, int offset, int length) {
		ByteArrayInputStream in = new ByteArrayInputStream(plainBytes, offset, length);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		encrypt(rawKey, in, out);
		return out.toByteArray();
	}

	/**
	 * 加密数据；
	 * 
	 * @param rawKey     未编码的原加密密钥；
	 * @param plainBytes 明文数据；；
	 * @param offset     明文输入偏移；
	 * @param length     明文输入长度；
	 * @param out        密文输出；
	 * @return 密文输出长度；
	 */
	@Override
	default int encrypt(byte[] rawKey, byte[] plainBytes, int offset, int length, OutputStream out) {
		ByteArrayInputStream in = new ByteArrayInputStream(plainBytes, offset, length);
		return encrypt(rawKey, in, out);
	}

	/**
	 * 加密数据；
	 * 
	 * @param rawKey     未编码的原加密密钥；
	 * @param plainBytes 明文数据；；
	 * @param offset     明文输入偏移；
	 * @param length     明文输入长度；
	 * @param out        密文输出；
	 * @return 密文输出长度；
	 */
	int encrypt(byte[] rawKey, InputStream in, OutputStream out);

	/**
	 * 解密数据；
	 * 
	 * @param DK          解密密钥；
	 * @param cipherBytes 密文数据；
	 * @return 明文数据；
	 */
	@Override
	default byte[] decrypt(DK key, byte[] cipherBytes) {
		ByteArrayInputStream in = new ByteArrayInputStream(cipherBytes);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		decrypt(key, in, out);
		return out.toByteArray();
	}

	/**
	 * 解密数据；
	 * 
	 * @param DK          解密密钥；
	 * @param cipherBytes 密文数据；
	 * @param offset      密文输入偏移；
	 * @param length      密文输入长度；
	 * @return 明文数据；
	 */
	@Override
	default byte[] decrypt(DK key, byte[] cipherBytes, int offset, int length) {
		ByteArrayInputStream in = new ByteArrayInputStream(cipherBytes, offset, length);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		decrypt(key, in, out);
		return out.toByteArray();
	}

	/**
	 * 解密数据；
	 * 
	 * @param DK          解密密钥；
	 * @param cipherBytes 密文数据；
	 * @param offset      密文输入偏移；
	 * @param length      密文输入长度；
	 * @param out         明文输出；
	 * @return 输出长度；
	 */
	@Override
	default int decrypt(DK key, byte[] cipherBytes, int offset, int length, OutputStream out) {
		ByteArrayInputStream in = new ByteArrayInputStream(cipherBytes, offset, length);
		return decrypt(key, in, out);
	}

	/**
	 * 解密数据；
	 * 
	 * @param key 解密密钥；
	 * @param in  密文输入；
	 * @param out 明文输出；
	 * @return 输出长度；
	 */
	int decrypt(DK key, InputStream in, OutputStream out);

	/**
	 * 解密数据；
	 * 
	 * @param rawKey      未编码的原解密密钥；
	 * @param cipherBytes 密文数据；
	 * @return 明文数据；
	 */
	@Override
	default byte[] decrypt(byte[] rawKey, byte[] cipherBytes) {
		ByteArrayInputStream in = new ByteArrayInputStream(cipherBytes);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		decrypt(rawKey, in, out);
		return out.toByteArray();
	}

	/**
	 * 解密数据；
	 * 
	 * @param rawKey      未编码的原解密密钥；
	 * @param cipherBytes 密文数据；
	 * @param offset      密文输入偏移；
	 * @param length      密文输入长度；
	 * @return 明文数据；
	 */
	@Override
	default byte[] decrypt(byte[] rawKey, byte[] cipherBytes, int offset, int length) {
		ByteArrayInputStream in = new ByteArrayInputStream(cipherBytes, offset, length);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		decrypt(rawKey, in, out);
		return out.toByteArray();
	}

	/**
	 * 解密数据；
	 * 
	 * @param rawKey      未编码的原解密密钥；
	 * @param cipherBytes 密文数据；
	 * @param offset      密文输入偏移；
	 * @param length      密文输入长度；
	 * @param out         明文输出；
	 * @return 输出长度；
	 */
	@Override
	default int decrypt(byte[] rawKey, byte[] cipherBytes, int offset, int length, OutputStream out) {
		ByteArrayInputStream in = new ByteArrayInputStream(cipherBytes, offset, length);
		return decrypt(rawKey, in, out);
	}

	/**
	 * 解密数据；
	 * 
	 * @param rawKey 未编码的原解密密钥；
	 * @param in     密文输入；
	 * @param out    明文输出；
	 * @return 输出长度；
	 */
	int decrypt(byte[] rawKey, InputStream in, OutputStream out);

}
